package app

import (
	"errors"
	"reflect"
	"strings"

	"gitee.com/tomatomeatman/golang-repository/bricks2/model/dbinfo"
)

var ()

// web控制层接口定义,用于规范控制层结构体
type Controller interface {
	GetModuleEntity(control Controller) (dbinfo.Entity, error) //对应模块数据实体
	GetModuleService(control Controller) (Service, error)      //对应模块业务实体
	GetModuleDao(control Controller) (Dao, error)              //对应模块数据处理实体
	RegisterUrl()                                              //http接口注册
	Enable() int                                               //控制操作,首位9不参与用7个数代表开关,0为不限制,1为限制
	CheckRepeatCombination() []string                          //检查待新增内容是否存在重复数据(多字段组合重复即重复)集合
	CheckRepeatAlone() map[string]int                          //检查待新增内容是否存在重复数据(单独字段重复即重复)集合
	IdValuePrefix() string                                     //记录编号值前缀,此属性用于给id字段添加前缀,以便于在分布式系统中进行数据合并,注意:前缀只有1个字符
	LikeTimeLimit() int                                        //模糊查询时是否要进行时间范围限制,默认900000天内,已经相当于不限制了
	SetOwner(owner Controller)                                 //设置父对象
	SimplName(control interface{}) string                      //获取控制器简称(没有Controller结尾)
}

// ---------------- 控制层默认接口实现 ----------------//

// 基类
type ControllerBaseFunc struct {
	owner Controller //指定上级
	// moduleEntity  dbinfo.Entity //对应模块数据实体
	// moduleService Service       //对应模块业务实体
	// enable                 int            //控制操作值集合
	// checkRepeatCombination []string       //检查待新增内容是否存在重复数据(多字段组合重复即重复)集合
	// checkRepeatAlone       map[string]int //检查待新增内容是否存在重复数据(单独字段重复即重复)集合
	// idValuePrefix          string         //记录编号值前缀,此属性用于给id字段添加前缀,以便于在分布式系统中进行数据合并
	// likeTimeLimit          float64        //模糊查询时是否要进行时间范围限制,默认限制7天内
}

/**
 * 设置父对象
 * @param owner
 */
func (control *ControllerBaseFunc) SetOwner(owner Controller) {
	control.owner = owner
}

// http接口注册
func (control *ControllerBaseFunc) RegisterUrl() {
	control.owner.RegisterUrl() //子类实现
}

// -- 控制操作,首位9不参与用7个数代表开关,0为不限制,1为限制 --//
// -- 7个数的控制分别是:删除、修改、查询、导出、统计、步骤值可逆、物理删除 --//
// -- 其中前5个为'是否仅创建者可操作'后续为其它控制开关 --//
func (control *ControllerBaseFunc) Enable() int {
	return 90000001
}

// 检查待新增内容是否存在重复数据(多字段组合重复即重复)集合
func (control *ControllerBaseFunc) CheckRepeatCombination() []string {
	return []string{}
}

// -- 检查待新增内容是否存在重复数据(单独字段重复即重复)集合 --//
func (control *ControllerBaseFunc) CheckRepeatAlone() map[string]int {
	return map[string]int{}
}

/**
 * 记录编号值前缀,此属性用于给id字段添加前缀,以便于在分布式系统中进行数据合并
 * 注意:前缀只有1个字符
 */
func (control *ControllerBaseFunc) IdValuePrefix() string {
	return ""
}

/**
 * 模糊查询时是否要进行时间范围限制,默认限制7天内
 */
func (control *ControllerBaseFunc) LikeTimeLimit() int {
	return 900000
}

/**
 * 获取模块数据实体
 */
func (control *ControllerBaseFunc) GetModuleEntity(controller Controller) (dbinfo.Entity, error) {
	moduleValue := reflect.ValueOf(controller).Elem().FieldByName("ModuleEntity")

	if moduleValue.Kind() != reflect.Ptr && moduleValue.Kind() != reflect.Struct {
		return nil, errors.New("未设置模块数据实体")
	}

	// //直接调用Now
	// nowMethod := moduleValue.MethodByName("New")
	// entityElem := nowMethod.Call(nil)[0].Interface()
	// result := entityElem.(dbinfo.Entity)

	// 获取 Entity 的反射值
	var entityElem reflect.Value
	if moduleValue.Kind() == reflect.Ptr {
		entityElem = reflect.New(moduleValue.Type().Elem())
	} else {
		entityElem = reflect.New(moduleValue.Type())
	}

	result := entityElem.Interface().(dbinfo.Entity)

	// result := entityElem.Interface().(dbinfo.Entity).New()

	return result, nil
}

/**
 * 获取模块业务实体
 */
func (control *ControllerBaseFunc) GetModuleService(controller Controller) (Service, error) {
	moduleValue := reflect.ValueOf(controller).Elem().FieldByName("ModuleService")

	if moduleValue.Kind() != reflect.Ptr && moduleValue.Kind() != reflect.Struct {
		return &ServiceBaseFunc{}, errors.New("未设置模块业务实体")
	}

	// 获取 Service 的反射值
	var serviceElem reflect.Value
	if moduleValue.Kind() == reflect.Ptr {
		serviceElem = reflect.New(moduleValue.Type().Elem())
	} else {
		serviceElem = reflect.New(moduleValue.Type())
	}

	service := serviceElem.Interface().(Service)
	service.SetOwner(service)

	return service, nil
}

/**
 * 获取模块数据访问实体
 */
func (control *ControllerBaseFunc) GetModuleDao(controller Controller) (Dao, error) {
	moduleValue := reflect.ValueOf(controller).Elem().FieldByName("ModuleDao")

	if moduleValue.Kind() != reflect.Ptr && moduleValue.Kind() != reflect.Struct {
		return &DaoBaseFunc{}, errors.New("未设置模块业务实体")
	}

	// 获取 Service 的反射值
	var daoElem reflect.Value
	if moduleValue.Kind() == reflect.Ptr {
		daoElem = reflect.New(moduleValue.Type().Elem())
	} else {
		daoElem = reflect.New(moduleValue.Type())
	}

	dao := daoElem.Interface().(Dao)
	dao.SetOwner(dao)

	return dao, nil
}

/**
 * 获取控制器简称(没有Controller结尾)
 * control interface{} 实际控制器对象
 */
func (ControllerBaseFunc) SimplName(control interface{}) string {
	name := reflect.TypeOf(control).String()

	iSt := strings.Index(name, ".")
	if iSt > -1 {
		name = name[iSt+1:]
	}

	name = strings.TrimSuffix(name, "Controller") //去掉结尾的'Controller'

	return name
}

// // 模块控制器初始化
// func ControllerInit(controller Controller) {
// 	moduleName := getSimplName(controller)
// 	if strings.HasSuffix(moduleName, "Controller") {
// 		moduleName = moduleName[:(len(moduleName) - 10)]
// 	}

// 	//-- 控制操作,首位9不参与用7个数代表开关,0为不限制,1为限制 --//
// 	//-- 7个数的控制分别是:删除、修改、查询、导出、统计、步骤值可逆、物理删除 --//
// 	//-- 其中前5个为'是否仅创建者可操作'后续为其它控制开关 --//
// 	globalvariable.RegisterVariable(moduleName+"_ModuleEnable", controller.Enable())

// 	//-- 检查待新增内容是否存在重复数据(多字段组合重复即重复)集合 --//
// 	globalvariable.RegisterVariable(moduleName+"_CheckRepeatCombination", controller.CheckRepeatCombination())

// 	//-- 检查待新增内容是否存在重复数据(单独字段重复即重复)集合 --//
// 	globalvariable.RegisterVariable(moduleName+"_CheckRepeatAlone", controller.CheckRepeatAlone())

// 	//-- 记录编号值前缀,此属性用于给id字段添加前缀,以便于在分布式系统中进行数据合并 --//
// 	//-- 注意:必须规划好各个模块的前缀,如果没有数据合并的需要则不需要设置,默认没有前缀 --//
// 	//-- 前缀只有1个字符 --//
// 	globalvariable.RegisterVariable(moduleName+"_IdValuePrefix", controller.IdValuePrefix())

// 	//-- 模糊查询时是否要进行时间范围限制,默认限制7天内 --//
// 	globalvariable.RegisterVariable(moduleName+"_LikeTimeLimit", controller.LikeTimeLimit()) //已经相当于不限制了

// 	controller.RegisterUrl() //接口注册
// }
